package futbol.tacticas.concursantes.Fresitas;

import java.awt.Color;
import java.awt.Point;
import java.util.Random;
import java.util.Vector;

import futbol.tacticas.Comando;
import futbol.tacticas.ComandoGolpearBola;
import futbol.tacticas.ComandoIrA;
import futbol.tacticas.ComandoTiroAPuerta;
import futbol.tacticas.SituacionJugadores;
import futbol.tacticas.concursantes.Tactica;

public class Fresitas implements Tactica{
	long marcador,marcaMiCampo,marcaSuCampo;
    long subMarcador=1;
    int golesMios,golesSuyos;
    long contadorBolaParada;
    
    boolean estadoCritico=false;
    boolean furonAnulado=false;
    double[] velocidadContrarios = new double[11];
    Point[] posicionContrarios = new Point[11];
    Point posicionBola = new Point(0,0);
    
    int[] asignaciones = new int[11];
    int inicioC=1; //inclusive
    int finC = 10; //exclusive
    int lejano1,lejano2;

    
    private int nValores[][]={
        {-155,0,6},
        {-100,100,4},
        {-120,30,4},
        {80,0,4},        
        {-100,-100,4},
        {20,100,4},
        {-20,30,4},
        {-20,-30,4},
        {20,-100,4},
        {120,30,4},
        {70,0,7} 
    };

    public String getNombre(){
        return "Fresitas";
    }
    
    public Color getColor1(){
        return Color.pink;
    }
    
    public Color getColor2(){
        return Color.pink;
    }
    
    public Color getColorNumero(){
        return Color.white;
    }
    
    public int getFuerza(int n){
        return nValores[n][2];
    }
    public int getXInicial(int n){
        return nValores[n][0];
    }
    
    public int getYInicial(int n){
        return nValores[n][1];
    }
    
    public Vector<Comando> getComandos(SituacionJugadores sj){
        

        Point bola=sj.getBola();
        Vector <Comando> com=new Vector();
        
        
        

        //$$$$$$$$$$$$$$$$$$$$$$4    INICIO FURÓN 
        com.add(new ComandoIrA(10, nValores[10][0], nValores[10][1]));
        if (norma( bola.getX()-sj.getMisJugadores()[10].getX() , bola.getY()-sj.getMisJugadores()[10].getY() )<40)
            jugadorMueveOptimizando(10,sj,com);
        com.add(new ComandoTiroAPuerta(10,0));
        //$$$$$$$$$$$$$$$$$$$$$$4    FIN FURÓN 
        
        
        
        
        //Medimos velocidades de los contrarios
        mideVelocidadesContrarios(sj);
        
        
        
                    
        //$$$$$$$$$$$$$$$$$$$$$$4    INICIO PORTERO 
        
        if (chequeaAlarmaPortero(sj)==true) jugadorMueveOptimizando(0,sj,com);
        else 
            muevePorteroSinAlarma(sj,com);

        com.add(new ComandoGolpearBola(0,100,0));
        
        //$$$$$$$$$$$$$$$$$$$$$$4    FIN PORTERO 
        
        
        
        
        asignaCubribles(sj);
        cubreTodos(sj,com);
        
        
        
        
        
        if ((marcador>=800)&&(golesMios==0)) furonAnulado=true;

        if (bola.getX()<0) marcaMiCampo++; else marcaSuCampo++;
        //System.out.println("Dominio: "+marcaMiCampo+"  "+marcaSuCampo);
        
        if ((bola.getX()>=160)&&(Math.abs(bola.getY())<30)) {golesMios++; subMarcador=0;}
        if  ((bola.getX()<=-160)&&(Math.abs(bola.getY())<30)) {golesSuyos++; subMarcador=0;}
        //System.out.println("Mios, tuyos : "+golesMios+"  "+golesSuyos);
        
        
        if ( (bola.getX()==posicionBola.getX()) && (bola.getY()==posicionBola.getY()) ) 
            contadorBolaParada++;
        else contadorBolaParada=0;
        //System.out.println("bola parada: "+contadorBolaParada);
        
        
        if (contadorBolaParada>100){
              
            //System.out.println("Estado estanco");
            if ( (golesSuyos>golesMios) || 
                 ((golesSuyos==golesMios)&&(bola.getX()<=0)&&(1800-marcador>=marcaSuCampo-marcaMiCampo)) || 
                 ((golesSuyos==golesMios)&&(bola.getX()>0)&&(1800-marcador<=marcaMiCampo-marcaSuCampo)) ) 
            
                com.add(new ComandoIrA(10,bola.getX(),bola.getY()));
        }
        
        
        
        
        //if (marcador%10==0)
        //System.out.println(marcador);
        /*
        if (marcador==5)
        for (int i=0; i<11; i++){
            System.out.println(velocidadContrarios[i]);
            System.out.println(" ");
        }
        */
        marcador++;
        subMarcador++;
        actualizaPosicionBola(sj);
        return com;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@   métodos    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    
    
    
    
    
    public double norma(double x,double y){
        return Math.sqrt(Math.pow(x,2)+Math.pow(y,2));
        
    }
    
    public double dameDistContrMasCercano(double x, double y,SituacionJugadores sj){
        int n= sj.getContrarioMasCerca(x,y);
        return norma(x-sj.getContrario()[n].getX(),y-sj.getContrario()[n].getY());
    }
    
    public void mideVelocidadesContrarios(SituacionJugadores sj){
        if (marcador==1) {
            posicionContrarios=sj.getContrario();
        }
        if (marcador==2) {
            for (int i=0;i<11;i++){
            velocidadContrarios[i] = Math.round( norma( posicionContrarios[i].getX()-sj.getContrario()[i].getX() , posicionContrarios[i].getY()-sj.getContrario()[i].getY() ) );
            if ((velocidadContrarios[i]<3)||(velocidadContrarios[i]>6)) velocidadContrarios[i]=6;
            }
        }
    }
    
    
    
    public int dameAmigoMasCercano(int n,SituacionJugadores sj){
     int pivote = 0;
     double pivote2 = 1000;
       Point[] misJugadores=sj.getMisJugadores() ;
       for (int i=1;(i<11);i++){
           //System.out.println("para jugador "+i+" la distancia es "+norma ( misJugadores[i].getX()-misJugadores[n].getX() , misJugadores[i].getY()-misJugadores[n].getY() ));
       if ((i!=n)&&(pivote2 > norma ( misJugadores[i].getX()-misJugadores[n].getX() , misJugadores[i].getY()-misJugadores[n].getY() ))){
                    pivote2 = norma ( misJugadores[i].getX()-misJugadores[n].getX() , misJugadores[i].getY()-misJugadores[n].getY() ); pivote=i;}
       }
               //System.out.println(" el mas cercano a "+n+" es "+pivote);
        return pivote;

    }

    
    public void jugadorMueveOptimizando(int nJug, SituacionJugadores sj, Vector<Comando> com){
        
    double p2x = sj.getMisJugadores()[nJug].getX();
    double p2y = sj.getMisJugadores()[nJug].getY();
    double p1x = sj.getBola().getX();
    double p1y = sj.getBola().getY();
    double vx = dameVelocidadBolaX(sj);
    double vy = dameVelocidadBolaY(sj);
    double x = dameProyeccionX(p1x,p1y,p2x,p2y,vx,vy);
    double y = dameProyeccionY(p1x,p1y,p2x,p2y,vx,vy);
    //llegará?
    double v = norma(dameVelocidadBolaX(sj),dameVelocidadBolaY(sj));
    double r = (v+1)*v/2;
    double t = norma(x-p1x,y-p1y);
    if (r<t) com.add(new ComandoIrA( nJug , (int)p1x+vx*(r-1)/v , (int)p1y+vy*(r-1)/v )); 
    else com.add(new ComandoIrA(nJug,(int)x,(int)y));    
    }
    
    
    
    public double dameProyeccionX(double p1x, double p1y, double p2x, double p2y, double vx, double vy){
        double r;
        if ((vx==0)&&(vy==0)) r=0;
        else r = -(p1x*vx-p2x*vx+p1y*vy-p2y*vy)/(Math.pow(vx,2)+Math.pow(vy,2));
    return (p1x+r*vx);
}
    
    public double dameProyeccionY(double p1x, double p1y, double p2x, double p2y, double vx, double vy){
        double r;
        if ((vx==0)&&(vy==0)) r=0;
        else r = -(p1x*vx-p2x*vx+p1y*vy-p2y*vy)/(Math.pow(vx,2)+Math.pow(vy,2));
    return (p1y+r*vy);  
}
    
    public double dameVelocidadBolaX(SituacionJugadores sj){
        return sj.getBola().getX()-posicionBola.getX();
    }
    
    
    public double dameVelocidadBolaY(SituacionJugadores sj){
        return sj.getBola().getY()-posicionBola.getY();
    }
    
    
    public void actualizaPosicionBola(SituacionJugadores sj){
        if (Math.abs(sj.getBola().getX())>=160) posicionBola=new Point(0,0);
        else;
        posicionBola=sj.getBola();
    }
  
    
    
    
    
    
    
    
    
    
    public  boolean chequeaAlarmaPortero(SituacionJugadores sj){
        
        
        double choque = sj.getBola().getY()+dameVelocidadBolaY(sj)*
                ((-160-sj.getBola().getX())/dameVelocidadBolaX(sj) );
        
        boolean a = ((Math.abs( choque ) < 32)&&(dameVelocidadBolaX(sj)<0));
        
        double d = norma ((sj.getBola().getX()+160)/(2.5),sj.getBola().getY());
        //double v = norma (dameVelocidadBolaX(sj),dameVelocidadBolaY(sj));
        //double r = (v+1)*v/2;
        //boolean b = r+40 > d;
        boolean b = d<70;
        
        //if (a==true) System.out.println("direccion peligrosa");
        
        /*
        if(a&&b){
            try{
        char caracter = (char) System.in.read(); 
            }catch(Exception e){}   
        }
        */
        return (a && b);
    }
    
    
    public void muevePorteroSinAlarma(SituacionJugadores sj,Vector<Comando> com){
        double signo = sj.getBola().getY()/Math.abs(sj.getBola().getY());
        if (sj.getBola().getY()==0) signo=1;
        double x=dameProyeccionX( sj.getBola().getX() , sj.getBola().getY() , -155 , 35*signo , -160-sj.getBola().getX() , -sj.getBola().getY() );
        double y=dameProyeccionY( sj.getBola().getX() , sj.getBola().getY() , -155 , 35*signo , -160-sj.getBola().getX() , -sj.getBola().getY() );
        com.add(new ComandoIrA(0,(int)x,(int)y)); 
    }
    
    
    
    
    
    public void asignaCubribles(SituacionJugadores sj){

        Point[] contrarios = sj.getContrario();
        Point[] propios = sj.getMisJugadores();
        
        if (subMarcador==1){
            
            //System.out.println("cucu");
            
            for (int i=0;i<11;i++) asignaciones[i]=i;
            
            double pivote;
            int[] contrariosAsignados = new int[11];
            int pivoteP=0;
            int pivoteP2=0;
            int[] propiosAsignados = new int [11];
            double dist,dist2;

            for (int i=0;i<finC-inicioC;i++){  //de entre todos los contrarios
                pivote=500;
                for (int k=0;k<11;k++){  //buscamos el (i+1)ésimo más lejano resp portería, finC-inicioC veces, que será el número pivoteP
                    dist2=norma(contrarios[k].getX()+160,contrarios[k].getY());
                    if ((dist2<pivote)&&( contrariosAsignados[k]!=1 )) { pivote=dist2; pivoteP=k; }
                }
                contrariosAsignados[pivoteP]=1;
                
                    dist=500;
                    for (int j=inicioC; j<finC;j++){ //para él buscamos el propio más cercano que no esté asignado
                        if  ((norma(contrarios[pivoteP].getX()-propios[j].getX(),contrarios[pivoteP].getY()-propios[j].getY())<dist) && ( propiosAsignados[j]!=1 )){
                                dist=norma(contrarios[pivoteP].getX()-propios[j].getX(),contrarios[pivoteP].getY()-propios[j].getY()); 
                                pivoteP2=j; 
                        }
                    }
                asignaciones[pivoteP2]=pivoteP;
                propiosAsignados[pivoteP2]=1;          
            }
        
            for(int f=0; f<11; f++) if (contrariosAsignados[f]==0) lejano1=f;
            for(int f=0; f<11; f++) if ((contrariosAsignados[f]==0)&&(f!=lejano1)) lejano2=f;
            
        } else {
            
            
            
            double pivote;
            int[] contrariosAsignados= new int[11];
            int pivoteP=0;
            double dist;
            
            for (int i=0; i<10; i++){ //vuelve a ordenar de cercano a lejano
                
                pivote=500;
                for (int j=0; j<11; j++){
                    dist=norma(contrarios[j].getX()+160,contrarios[j].getY());
                    if ((dist<pivote)&&(contrariosAsignados[j]!=1)) {pivoteP=j; pivote=dist;}
                }
                contrariosAsignados[pivoteP]=1;
                
                if ( (i<9) && ((pivoteP==lejano1)||(pivoteP==lejano2)) ) {subMarcador=0; //System.out.println("reseteado");
                                                                         }
                  
            } 
            
        }

        return;
    }
    
    

    
    
    
    public void cubre(int nJug, int nCon, SituacionJugadores sj, Vector<Comando> com){
        
        double x = sj.getBola().getX() - sj.getContrario()[nCon].getX();
        double y = sj.getBola().getY() - sj.getContrario()[nCon].getY();
        double n = norma(x,y);
        double nx = sj.getContrario()[nCon].getX()+(x/n)*20;
        double ny = sj.getContrario()[nCon].getY()+(y/n)*20;
        com.add(new ComandoIrA(nJug,(int)nx,(int)ny)); 
        
        //if (norma(  sj.getBola().getX()-sj.getMisJugadores()[nJug].getX()  ,  sj.getBola().getY()-sj.getMisJugadores()[nJug].getY())<20 ){
           double lx,ly;
        if (furonAnulado==false){
            lx = sj.getMisJugadores()[10].getX()-sj.getBola().getX();
            ly = sj.getMisJugadores()[10].getY()-sj.getBola().getY();
        } else {
            double pivote=0;
            int pivoteP=0;
            int nJ=0;
            double d;
            for (int i=0;i<27;i++) {
                nJ=sj.getContrarioMasCerca(160,Math.pow(-1,i)*i);
                d=norma( sj.getContrario()[nJ].getX()-160 , sj.getContrario()[nJ].getY()-Math.pow(-1,i)*i );
                if ( d>pivote ) {
                    pivote=d;
                    pivoteP=i;
                }
            }
            lx = 160-sj.getBola().getX();
            ly = Math.pow(-1,pivoteP)*pivoteP-sj.getBola().getY();
            //System.out.println(Math.pow(-1,pivoteP)*pivoteP);
        }
        
            if ((lx*x+ly*y)<0) //producto escalar negativo
                if ((lx*y-ly*x)>0) //producto vectorial positivo, primer factor lx,ly
                    {lx=y;
                     ly=-x;}
                else{lx=-y;
                     ly=x;}
            com.add(new ComandoGolpearBola( nJug , sj.getBola().getX()+lx*100 , sj.getBola().getY()+ly*100 ));
        //}
         
        
    }
    
    
    
    public void cubreTodos(SituacionJugadores sj, Vector<Comando> com){
        
        for (int i=inicioC;i<finC;i++){
            cubre(i,asignaciones[i],sj,com);   
        }
        return;
    }
    
    
    
    
    
    
}